#include <stdio.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/x509.h>

#include <openssl/ssl.h>

#include <openssl/pem.h>

#include <openssl/err.h>

#include <sys/socket.h>

#include <unistd.h>
//#include <openssl/ssl_locl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netdb.h>
#include <stdlib.h>
#include <iconv.h>
char *host = "hq.sinajs.cn";
//char *id = "sh600519";
char *id[] ;
//#define CERTSERVER "/tmp/testopenssl/demoCA/cacert.pem"

//#define KEYSERVER "/tmp/testopenssl/demoCA/private/cakey.pem"

#define CERTSERVER "SS.pem"

#define KEYSERVER "SS.key.pem"

#define SM2_SERVER_ENC_CERT "SE.pem"

#define SM2_SERVER_ENC_KEY "SE.key.pem"

#define CHK_ERR(err, s) if((err) == -1) { perror(s); return -1; }else printf("%s success!\n",s);

#define CHK_RV(rv, s) if((rv) != 1) { printf("%s error\n", s); return -1; }else printf("%s success!\n",s);

#define CHK_NULL(x, s) if((x) == NULL) { printf("%s error\n", s); return -1; }else printf("%s success!\n",s);

#define CHK_SSL(err, s) if((err) == -1) { ERR_print_errors_fp(stderr); return -1;}else printf("%s success!\n",s);

#define __owur const SSL_METHOD *GMTLS_server_method(void);

char *substring(char *dst,char *src,int start,int len)
{
	char *p=dst;
	char *q=src;
	int length=strlen(src);
	if(start>=length||start<0)
		return NULL;
	if(len>length)
		len=length-start;
	q+=start;
	while(len--)
	{
		*(p++)=*(q++);
	}
	*(p++)='\0';
	return dst;
}
char* gb18030_to_utf_8(const char *src)
{
 char* re;
 const char *sfrom = src;

 size_t   slen = strlen(sfrom);
 if (slen > (size_t)800)
 {
  slen = 800;
 }
 iconv_t cd;
 if((cd = iconv_open("UTF-8", "GB18030")) < 0)
     return re;
 char *sin  = (char *)sfrom;
 char sto[800]={0};
 char *dout = sto;
 size_t  dlen = 800;
 if(iconv(cd, &sin, &slen, &dout, &dlen) < 0)
        return re;
    iconv_close(cd);
    re = sto;
    return re;
}

int readHttp(int sockfd, char *data)
{
    char str[100] = "";
    read(sockfd, str, 9);
    printf("str==%s\n",str);
    memset(str, 0, sizeof(str));
    read(sockfd, str, 3);
    printf("str==%s\n",str);
    if(atoi(str) == 200){
        read(sockfd, str, 46);
	printf("str==%s\n",str);
        memset(str, 0, sizeof(str));
        read(sockfd, str, 3);
        printf("str==%s\n",str);
        int count = atoi(str);
        read(sockfd, str, 81);
	printf("%s\n",str);
        read(sockfd, data, count);
        return 0;
    }

    return -1;
}
char* get_result(char *host,char *id,char buf[4096] )
{
    //scanf("%s",id);
   char string[1024];
   strcpy(string,buf);
     id = string;
    printf("string=%ls",string);
    printf("id=%ls",id);
    int sockfd;
    int len;
    char str[32];
    struct hostent *hptr = gethostbyname(host);
    printf("ip address = %s\n", inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)));
    struct sockaddr_in address;
    int result;
    char strings[80];
    sprintf(strings, "GET /list=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", id, host);

    char ch;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(str);
    address.sin_port = htons(80);
    len = sizeof(address);
    result = connect(sockfd, (struct sockaddr *)&address, len);
    if(result == -1){
        perror("connect error");
        return 1;
    }

    char data[1000] = "";
    char data1[1000]="";
    write(sockfd, strings, strlen(strings));
    if(0 == readHttp(sockfd, data));
    //printf("data = %s\n", data);
    //printf("data11=%s\n",gb18030_to_utf_8(data));
    close(sockfd);
    strcpy(data1,gb18030_to_utf_8(data));
    char data2[]="";
    strcpy(data2,substring(data2,data1,23,219));
    //printf("dfdsfsdf==%s\n",data2);
   // printf("data = %s\n", data1);
    return substring(data2,data1,23,219);
}

int main()
{

	int rv, err;

	SSL_CTX *ctx = NULL;

	SSL_METHOD *meth = NULL;

	int listen_sd;

	int accept_sd;

	struct sockaddr_in socketAddrServer,socketAddrClient;

	socklen_t socketAddrClientLen;

	SSL *ssl = NULL;

	char buf[4096];

	rv = SSL_library_init();

	CHK_RV(rv, "SSL_library_init");

	meth = (SSL_METHOD *)GMTLS_server_method();

	ctx = SSL_CTX_new(meth);

	CHK_NULL(ctx, "SSL_CTX_new");

	rv = SSL_CTX_use_certificate_file(ctx, CERTSERVER, SSL_FILETYPE_PEM);

	CHK_RV(rv, "SSL_CTX_use_certicificate_file");

	rv = SSL_CTX_use_PrivateKey_file(ctx, KEYSERVER, SSL_FILETYPE_PEM);

	CHK_RV(rv, "SSL_CTX_use_PrivateKey_file");

	rv = SSL_CTX_check_private_key(ctx);

	CHK_RV(rv, "SSL_CTX_check_private_key");

	rv = SSL_CTX_use_certificate_file(ctx, SM2_SERVER_ENC_CERT, SSL_FILETYPE_PEM);

	CHK_RV(rv, "SSL_CTX_use_certicificate_file2");

	rv = SSL_CTX_use_PrivateKey_file(ctx, SM2_SERVER_ENC_KEY, SSL_FILETYPE_PEM);

	CHK_RV(rv, "SSL_CTX_use_PrivateKey_file2");

	rv = SSL_CTX_check_private_key(ctx);

	CHK_RV(rv, "SSL_CTX_check_private_key2");

	SSL_CTX_set_security_level(ctx, 0);

	listen_sd = socket(AF_INET, SOCK_STREAM, 0);

	CHK_ERR(listen_sd, "socket");

	memset(&socketAddrServer, 0, sizeof(socketAddrServer));

	socketAddrServer.sin_family = AF_INET;

	socketAddrServer.sin_port = htons(8443);

	socketAddrServer.sin_addr.s_addr = INADDR_ANY;

	err = bind(listen_sd, (struct sockaddr *)&socketAddrServer, sizeof(socketAddrServer));

	CHK_ERR(err, "bind");

	err = listen(listen_sd, 5);

	CHK_ERR(err, "listen");

	socketAddrClientLen = sizeof(socketAddrClient);

	accept_sd = accept(listen_sd, (struct sockaddr *)&socketAddrClient, &socketAddrClientLen);

	CHK_ERR(accept_sd, "accept");

	close(listen_sd);

	printf("Connect from %lx, port %x\n", socketAddrClient.sin_addr.s_addr, socketAddrClient.sin_port);

	ssl = SSL_new(ctx);

	CHK_NULL(ssl, "SSL_new");

	rv = SSL_set_fd(ssl, accept_sd);

	CHK_RV(rv, "SSL_set_fd");

	rv = SSL_accept(ssl);

	CHK_RV(rv, "SSL_accpet");

	/* Check for Client authentication error */

	if (SSL_get_verify_result(ssl) != X509_V_OK) {

		printf("SSL Client Authentication error\n");

		SSL_free(ssl);

		close(accept_sd);

		SSL_CTX_free(ctx);

		exit(0);

	}

	/*Print out connection details*/

	printf("SSL connection on socket %x,Version: %s, Cipher: %s\n",

		accept_sd,

		SSL_get_version(ssl),

		SSL_get_cipher(ssl));

	rv = SSL_read(ssl, buf, sizeof(buf) - 1);

	CHK_SSL(rv, "SSL_read");

	buf[rv] = '\0';

	printf("Got %d chars :%s\n", rv, buf);

	rv = SSL_write(ssl, "I accept your request", strlen("I accept your request"));
	//printf("len==%d\n",rv);
	//printf("len==%d\n",rv);
	char shares[1000]="";
	strcpy(shares,get_result(host,id,buf));
	//printf("查询的股票信息：\n");
        rv = SSL_write(ssl,shares, strlen(shares));
	//printf("len==%d\n",rv);

	close(accept_sd);

	SSL_free(ssl);

	SSL_CTX_free(ctx);

	return 0;

}


